package com.example.onlinemonitoring.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.onlinemonitoring.AOP.RepeatSubmit;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.FileUtil;
import com.example.onlinemonitoring.Util.tem.SensorAbstractBaseService;
import com.example.onlinemonitoring.autoRun.ComRunner;
import com.example.onlinemonitoring.autoRun.ComTcp;
import com.example.onlinemonitoring.comCenter.DfCom;
import com.example.onlinemonitoring.dao.AppalarmMapper;
import com.example.onlinemonitoring.dao.AppstationMapper;
import com.example.onlinemonitoring.model.Appalarm;
import com.example.onlinemonitoring.model.Appdevice;
import com.example.onlinemonitoring.model.AppdeviceMobile;
import com.example.onlinemonitoring.model.AppdeviceTemp;
import com.example.onlinemonitoring.model.Appstation;
import com.example.onlinemonitoring.model.common.sensor;
import com.example.onlinemonitoring.query.QueryObject;
import com.example.onlinemonitoring.model.common.MyResult;
import com.example.onlinemonitoring.model.common.factorydeletion;
import com.example.onlinemonitoring.serviceImpl.AppalarmServiceImpl;
import com.example.onlinemonitoring.serviceImpl.AppdeviceServiceImpl;
import com.example.onlinemonitoring.serviceImpl.AppdeviceTempServiceImpl;
import com.example.onlinemonitoring.Util.LanguageManager;
import freemarker.core.ParseException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import tk.mybatis.mapper.entity.Example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;

import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Api(value = "设备维护表", tags = { "设备维护接口" })
@RestController
public class deviceController {
    @Autowired
    AppdeviceServiceImpl appdeviceimpl;
    @Autowired
    AppdeviceTempServiceImpl appdevicetempimpl;
    @Autowired
    AppalarmServiceImpl appalarmserviceimpl;
    @Autowired
    AppstationMapper appstationmapper;
    @Autowired
    BeanFactory beanFactory;
    @Autowired
    private ComRunner.AsyncService asyncService;
    @Autowired
    LanguageManager languageManager;

    @ApiOperation(value = "查询设备", notes = "查询设备")
    @ResponseBody
    @GetMapping("/selectDevice")
    public MyResult<Appdevice> selectDevice(@RequestParam(value = "isshow", required = false) Integer isshow) {
        Example example = new Example(Appdevice.class);
        Example.Criteria criteria = example.createCriteria();
        if (isshow != null) {
            criteria.andEqualTo("isshow", isshow);
        }
        // example.setOrderByClause("ordernum asc");
        example.orderBy("ordernum").asc();
        return appdeviceimpl.getList(example);
    }

    @ApiOperation(value = "查询设备数量（移动端）", notes = "查询设备数量（移动端）")
    @ResponseBody
    @GetMapping("/selectDeviceCount")
    public MyResult<AppdeviceMobile> selectDeviceCount(
            @RequestParam(value = "isshow", required = false) Integer isshow) {
        MyResult<AppdeviceMobile> result = new MyResult<AppdeviceMobile>();
        Example example = new Example(Appdevice.class);
        Example.Criteria criteria = example.createCriteria();
        if (isshow != null) {
            criteria.andEqualTo("isshow", isshow);
        }
        // example.setOrderByClause("CONVERT(name USING gbk)");
        example.orderBy("ordernum").asc();
        List<Appdevice> devicelist = appdeviceimpl.getList(example).getData();
        List<AppdeviceMobile> totaldevicelists = new ArrayList<AppdeviceMobile>();
        for (int j = 0; j < devicelist.size(); j++) {
            if (!devicelist.get(j).getSimple().contains("61850") && !devicelist.get(j).getType().equals("转发")) {
                int stationid = devicelist.get(j).getStationid();
                int devicegroup = devicelist.get(j).getDevicegroup();
                try {
                    SensorAbstractBaseService<sensor, sensor> service = (SensorAbstractBaseService<sensor, sensor>) beanFactory
                            .getBean(devicelist.get(j).getSimple() + "ServiceImpl");
                    int totalcount = service.getTotalCount(stationid, devicegroup);
                    AppdeviceMobile adm = new AppdeviceMobile();
                    BeanUtils.copyProperties(devicelist.get(j), adm);
                    adm.setTotalcount(totalcount);
                    totaldevicelists.add(adm);
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        }
        if (totaldevicelists.size() != 0) {
            result.setCode(0);
            result.setMsg("success");
            result.setCount(totaldevicelists.size());
            result.setData(totaldevicelists);
        } else {
            result.setCode(1);
            result.setMsg("数据为空");
        }
        return result;
    }

    @ApiOperation(value = "删除设备", notes = "删除设备")
    @ResponseBody
    @GetMapping("/deleteDevice")
    public MyResult<Integer> deleteDevice(@RequestParam(value = "id", required = true) Integer id) {
        MyResult<Integer> m = new MyResult<Integer>();
        Appdevice record = new Appdevice();
        record.setId(id);
        record = appdeviceimpl.selectByPrimaryKey(record);
        if (record != null) {
            if (!record.getSimple().contains("61850") && !record.getType().equals("转发")) {
                SensorAbstractBaseService<sensor, sensor> service = (SensorAbstractBaseService<sensor, sensor>) beanFactory
                        .getBean(record.getSimple() + "ServiceImpl");
                service.Delete(record);
            }
            if (appdeviceimpl.deleteByPrimaryKey(record) >= 1) {
                m.setMsg(languageManager.getLan().getDeleteSuccess());
                m.setCode(0);
            } else {
                m.setMsg(languageManager.getLan().getDeleteFailed());
                m.setCode(1);
            }
            return m;
        } else {
            m.setMsg(languageManager.getLan().getDeleteFailed());
            m.setCode(1);
            return m;
        }
    }

    @ApiOperation(value = "查询可用串口", notes = "查询可用串口")
    @ResponseBody
    @GetMapping("/selectAvailablePort")
    public MyResult<String> selectAvailablePort() {
        ComRunner.info.serieslist = "";
        MyResult<String> m = new MyResult<String>();
        List<String> portlist = new ArrayList<>();
        try {
            ComRunner.info.send("INFO");
            // 设置超时时间10s
            Long timestamp = System.currentTimeMillis() + 1000 * 10;
            boolean skip = false;
            while (System.currentTimeMillis() < timestamp && !skip) {
                if (!"".equals(ComRunner.info.serieslist.trim())) {
                    System.out.println("comTcp.serieslist:" + ComRunner.info.serieslist);
                    // 分割字符
                    String[] split = ComRunner.info.serieslist.split("\\|");
                    if (split.length != 0) {
                        for (String com : split) {
                            portlist.add(com);
                        }
                        portlist.add("USB0");
                        skip = true;
                    }
                } else {
                    skip = System.currentTimeMillis() >= timestamp;
                }
            }
        } catch (Exception ex) {
            m.setMsg("串口列表查找失败！");
            m.setCode(1);
        }
        m.setMsg(languageManager.getLan().getSerialPortListSuccess() + "！");
        m.setCode(0);
        m.setData(portlist);
        return m;
    }

    @ApiOperation(value = "查询模板", notes = "查询模板")
    @ResponseBody
    @GetMapping("/selectDeviceTemp")
    public MyResult<AppdeviceTemp> selectDeviceTemp() {
        Example example = new Example(AppdeviceTemp.class);
        example.setOrderByClause("CONVERT(name USING gbk)");
        return appdevicetempimpl.getList(example);
    }

    @ApiOperation(value = "查询设备明细", notes = "查询设备明细")
    @ResponseBody
    @GetMapping("/selectDeviceDetail")
    public MyResult<Appdevice> selectDeviceDetail(@RequestParam(value = "id", required = true) Integer id) {
        Example example = new Example(Appdevice.class);
        Example.Criteria criteria = example.createCriteria();
        if (id != null) {
            criteria.andEqualTo("id", id);
        }
        return appdeviceimpl.getList(example);
    }

    @SuppressWarnings("unchecked")
    @Transactional
    @ApiOperation(value = "端口配置更新设备参数", notes = "端口配置更新设备参数")
    @ResponseBody
    @RequestMapping(value = "/updateDeviceDetail", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public MyResult<Integer> updateDeviceDetail(@RequestBody String jsonParam,
            @RequestParam(value = "id", required = false) Integer id) {
        JSONObject object = JSONObject.parseObject(jsonParam);
        MyResult<Integer> m = new MyResult<Integer>();
        Appdevice record = object.toJavaObject(Appdevice.class);
        if (record.getSensor() != null && !record.getSensor().equals("")) {
            String autoadd = object.getString("autoadd");
            String clearmon = object.getString("clearmon");

            if ((record.getCom() == null && record.getIp() == null) || record.getAddrmax() == null
                    || record.getAddrmin() == null || (record.getBaudrate() == null && record.getPort() == null)
                    || record.getTimersp() == null) {
                m.setMsg(languageManager.getLan().getMandatoryFieldsCannotBeEmpty());
                m.setCode(1);
                return m;
            }
            if (clearmon == null)
                clearmon = "0";
            if (autoadd == null)
                autoadd = "0";
            if (record.getAddrmax() < record.getAddrmin()) {
                m.setMsg(languageManager.getLan().getMaxAddressMustBeGreaterThanMinAddress());
                m.setCode(1);
                return m;
            }
            if (clearmon.equals("1")) {
                SensorAbstractBaseService<sensor, sensor> service = (SensorAbstractBaseService<sensor, sensor>) beanFactory
                        .getBean(record.getSimple() + "ServiceImpl");
                service.Delete(record);
                Example example = new Example(Appalarm.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("stationid", record.getStationid());
                criteria.andEqualTo("devicegroup", record.getDevicegroup());
                criteria.andEqualTo("deviceid", record.getId());
                appalarmserviceimpl.deleteByExample(example);
            }
            if (autoadd.equals("1")) {
                SensorAbstractBaseService<sensor, sensor> service = (SensorAbstractBaseService<sensor, sensor>) beanFactory
                        .getBean(record.getSimple() + "ServiceImpl");
                if (service.Add(record) == 0) {
                    m.setMsg(languageManager.getLan().getAddMonitoringPointFailed());
                    m.setCode(1);
                    return m;
                }
            }
        }
        if (id == null) {// 新增
            record.setId(null);
            if (appdeviceimpl.insertSelective(record) >= 1) {
                m.setMsg(languageManager.getLan().getAddDeviceSuccess());
                m.setCode(0);
            } else {
                m.setMsg(languageManager.getLan().getAddDeviceFailed());
                m.setCode(1);
            }
        } else {// 修改
            record.setId(id);
            if (appdeviceimpl.updateByPrimaryKeySelective(record) >= 1) {
                m.setMsg(languageManager.getLan().getModifyDeviceSuccess());
                m.setCode(0);
            } else {
                m.setMsg(languageManager.getLan().getModifyDeviceFailed());
                m.setCode(1);
            }
        }
        try {
            if (record.getSimple().equals("df")) {// 总站转发需要同步61850配置文件
                String filepath = "";
                if (System.getProperty("os.name").toLowerCase().contains("win")) {
                    filepath = System.getProperty("user.dir") + "\\iec61850conf.xml";
                } else {
                    filepath = System.getProperty("user.dir") + "/iec61850conf.xml";
                }
                if (!filepath.equals("")) {
                    System.out.println(filepath);
                    String filestr = FileUtil.readFile(filepath);
                    if (record != null && record.getSubswitch() != null && !record.getSubswitch().equals("")) {
                        String[] subswitch = record.getSubswitch().split(",");
                        for (int i = 0; i < subswitch.length; i++) {
                            if (subswitch[i].split("|")[0].equals("1")) {
                                String target = "<" + DfCom.iec61850Cof[i] + ">0" + "</" + DfCom.iec61850Cof[i] + ">";
                                String rep = "<" + DfCom.iec61850Cof[i] + ">1" + "</" + DfCom.iec61850Cof[i] + ">";
                                filestr = filestr.replaceAll(target, rep);
                            } else if (subswitch[i].split("|")[0].equals("0")) {
                                String target = "<" + DfCom.iec61850Cof[i] + ">1" + "</" + DfCom.iec61850Cof[i] + ">";
                                String rep = "<" + DfCom.iec61850Cof[i] + ">0" + "</" + DfCom.iec61850Cof[i] + ">";
                                filestr = filestr.replaceAll(target, rep);
                            }
                        }
                    }
                    FileUtil.writeFile(filepath, filestr);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            // TODO: handle exception
        }

        return m;
    }

    @ApiOperation(value = "开关设备", notes = "开关设备")
    @ResponseBody
    @GetMapping("/openorclose")
    synchronized public MyResult<Integer> openorclose(
            @RequestParam(value = "id", required = false) Integer id,
            @RequestParam(value = "installed", required = false) Integer installed) {
        MyResult<Integer> m = new MyResult<Integer>();
        Appdevice record = new Appdevice();
        record.setId(id);
        record.setInstalled(installed);
        boolean skip = false;
        // 查询当前设备com口
        Appdevice appdevice = appdeviceimpl.selectByPrimaryKey(record);
        if (appdevice.getCommunicationmode() == 1) {
            if (appdevice.getCom() != null && installed == 1) {
                // 判断当前数据库中是否有已经打开的同com口
                Example example = new Example(Appdevice.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("installed", 1);
                criteria.andEqualTo("com", appdevice.getCom());
                criteria.andNotEqualTo("id", id);
                List<Appdevice> appdevices = appdeviceimpl.selectByExample(example);
                if (appdevices != null && !appdevices.isEmpty()) {
                    m.setMsg(languageManager.getLan().getOpenFailedPortInUse());
                    m.setCode(1);
                    return m;
                }
            }
            // 设置超时时间10s
            Long timestamp = System.currentTimeMillis() + 1000 * 3;
            Integer index = CommPortManager.strGetNum(appdevice.getCom());
            // 重置串口信息返回状态
            try {
                ComRunner.ct[index].openOrCloseMap.put(index, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 获取当前开启设备
            if (installed == 1) {
                // 异步通知开启串口
                asyncService.runAppdevice(appdevice);
                // 设置默认返回值
                m.setMsg(languageManager.getLan().getOpenFailedRetry());
                m.setCode(1);
            } else {
                // 异步通知关闭串口
                try {
                    ComRunner.devmap.get(index).closeComByTcp();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                m.setMsg(languageManager.getLan().getCloseFailedRetry());
                m.setCode(1);
            }
            // 判断超时时间内串口是否开启或关闭,并更新串口状态到数据库
            while (System.currentTimeMillis() < timestamp && !skip) {
                // 判断是否接收到tcp服务器操作串口信息返回
                if (ComRunner.ct[index].openOrCloseMap.get(index) != null) {
                    // 打开状态
                    if (ComRunner.ct[index].openOrCloseMap.get(index) == 1 && installed == 1) {
                        m.setMsg(languageManager.getLan().getOpenSuccess());
                        m.setCode(0);
                    } else if (ComRunner.ct[index].openOrCloseMap.get(index) == 0 && installed == 0) {
                        m.setMsg(languageManager.getLan().getCloseSuccess());
                        m.setCode(0);
                    } else {
                        // 操作异常
                        return m;
                    }
                    if (appdeviceimpl.updateByPrimaryKeySelective(record) >= 1) {
                        if (installed == 0) {
                            ComRunner.devmap.remove(index);
                        }
                        return m;
                    } else {
                        // 数据库更新失败,还原串口状态,异步操作不等待返回
                        if (installed == 1) {
                            ComRunner.devmap.get(index).closeComByTcp();
                        } else {
                            asyncService.runAppdevice(appdevice);
                        }
                        m.setMsg(languageManager.getLan().getDatabaseConnectionFailed());
                        m.setCode(1);
                        return m;
                    }
                } else {
                    skip = System.currentTimeMillis() >= timestamp;
                }
            }

        } else {
            if (appdeviceimpl.updateByPrimaryKeySelective(record) >= 1) {
                m.setMsg(languageManager.getLan().getOperationSuccess());
                m.setCode(0);
                return m;
            } else {
                m.setMsg(languageManager.getLan().getDatabaseConnectionFailed());
                m.setCode(1);
                return m;
            }
        }
        return m;
    }

}

// [{"id":1,"enable":0},{"id":7,"enable":0},{"id":8,"enable":1},{"id":9,"enable":1},{"id":10,"enable":1},{"id":11,"enable":1},{"id":12,"enable":1},{"id":34,"enable":1},{"id":35,"enable":1},{"id":36,"enable":1},{"id":37,"enable":1},{"id":38,"enable":1},{"id":39,"enable":1},{"id":40,"enable":1},{"id":41,"enable":1},{"id":42,"enable":1},{"id":43,"enable":1},{"id":44,"enable":1},{"id":45,"enable":1},{"id":46,"enable":1},{"id":47,"enable":1},{"id":48,"enable":1},{"id":49,"enable":1},{"id":50,"enable":1},{"id":51,"enable":1},{"id":52,"enable":1},{"id":53,"enable":1},{"id":54,"enable":1},{"id":55,"enable":1},{"id":56,"enable":1},{"id":57,"enable":1},{"id":58,"enable":1},{"id":59,"enable":1},{"id":60,"enable":1},{"id":61,"enable":1},{"id":62,"enable":1}]